#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include "includes.h"

#define COMMAND_SIZE 10
#define MAX_INT 20 /*Use something a little bigger than max digit size of 2147483647*/  
#define INCREMENT 10 /*Defines the 10 millisecond increments of input files*/
#define SEC_MILLI 1000 /*Conversion factor of seconds to milliseconds*/
#define BASE      10 /*Base 10 Used in helper functions below*/
#define IOSIZE 8192 /* IO size in bytes */

static struct proc_info *proc;
static long pid = 0;
static int eof = 0;
static int got_next = 1;

void reader()
{
	char c, command[COMMAND_SIZE], startTime[MAX_INT], CPUTime[MAX_INT], IOCount[MAX_INT];
	int ct, name, strtTime,CPUT,IOC;
	long start, bytes, io_ops, time_remaining;
	double cpu;
	
	
	/*Flags referencing segment of line sucessfully in*/
	name = 0;
 	strtTime = 0;
	CPUT = 0;
	IOC = 0;
	ct = 0;

	/*Read In Command Name*/
	while(1)
	{	
		c = getc(stdin);
		/* check if eof and set flag*/
		if(feof(stdin))
		{
			eof=1;
		}
		/*Break on eof */ 
		if (eof) { return;}

		if(c == ' ' || c == '\t')
		{
			/*Null Terminate*/
			command[ct] = '\0';
			/*Chew up spaces between inputs*/
			while(c == ' ' || c == '\t')
			{
				c = getc(stdin);
				
			}
			name = 1;
			/*Note c will have first digit for startTime*/
		}
		else
		{
			command[ct++] = c;
		}	
		if(name) break;	
	}
	ct = 0;
	/*Read in arrival time*/
	while(1)
	{
		if(c == ' ' || c == '\t')
		{
			/*Null Terminate*/
			startTime[ct] = '\0';
			/*Chew up spaces between inputs*/
			while(c == ' ' || c == '\t' )
			{
				c = getc(stdin);
			}
			strtTime = 1;
			/*Note c will have first digit for cpuTime*/
		}
		else
		{
			startTime[ct++] = c;
			c = getc(stdin);
		}
		if(strtTime) break;		
	}
	ct = 0;
	/*Read in running time of process*/
	while(1)
	{
		if(c == ' ' || c == '\t')
		{
			/*Null Terminate*/
			CPUTime[ct] = '\0';
			/*Chew up spaces between inputs*/
			while(c == ' ' || c == '\t' )
			{
				c = getc(stdin);
			}
			CPUT = 1;
			/*Note c will have first digit for IOCount*/
		}
		else
		{
			CPUTime[ct++] = c;
			c = getc(stdin);
		}
		if(CPUT) break;		
	}
	ct = 0;
	/*Read in Number of ios*/
	while(1)
	{
		if( c == '\n')
		{
			/*Null Terminate*/
			IOCount[ct] = '\0';
			IOC = 1;
		}
		else
		{
			IOCount[ct++] = c;
			c = getc(stdin);
		}
		if(IOC) break;		
	}
	/*Now that the input buffers are filled create the struct and fill data*/
	
	/*Convert startTime buffer*/	
	start = strtol(startTime, NULL,BASE);
	
	/*Convert CPUTime buffer and convert to milliseconds*/
	cpu = strtod(CPUTime, NULL);	
	time_remaining = cpu * SEC_MILLI;

	/*Convert IOCount buffer*/
	/*Special case if num ios is zero*/
	bytes = strtol(IOCount, NULL, BASE);
	


	/*Calculations for relevant data*/
	io_ops = (long)((bytes + IOSIZE - 1)/IOSIZE);

	if(io_ops > time_remaining)
	{
		proc->time_to_next_io = 1;
		proc->io_interval = 1;
	}
	else
	{
		/*Special Case with 0*/
		if(io_ops == 0)
		{
			proc->time_to_next_io = -1;			
			proc->io_interval = -1;
		}
		/*Special Case with 1*/
		/*Divide by two instead of 1 to make io happen in middle*/
		else if(io_ops == 1)
		{
			proc->time_to_next_io = time_remaining/2;			
			proc->io_interval = time_remaining/2;
		}

		/*ios do not divide evenly*/
		else if(!(time_remaining % io_ops))
		{
			proc->time_to_next_io = (time_remaining-(time_remaining%io_ops))/(io_ops);
			proc->io_interval = (time_remaining-(time_remaining%io_ops))/(io_ops);

		}
		/*ios do divide evenly*/
		else
		{
			proc->time_to_next_io = time_remaining/(io_ops);			
			proc->io_interval = time_remaining/(io_ops);
		}
	}

	proc->arrival_time = start*INCREMENT;
	proc->time_remaining = time_remaining;
	proc->ios_remaining = io_ops;
	proc->last_runtime = 0;
	proc->priority_level = 0;
	proc->pid = pid;
	pid++;
	return;
}


long reader_next_event_time()
{
  /*If a new process event 
    occured get next file entry*/
  if(got_next)
    {
      /*Make a new proc*/
      proc = (struct proc_info*)malloc(sizeof(struct proc_info));
      if(proc == NULL){printf("Failed Allocate Memory");exit(-1);}
      
      /* initialize values in proc */
      proc->arrival_time = -1;
      proc->time_remaining = 0;
      proc->time_to_next_io = 0;
      proc->pid = 0;
      proc->ios_remaining = 0;
      proc->io_interval = 0;
      proc->last_runtime = 0;
      proc->priority_level = 0;
      proc->finish_time = 0;
		
      reader();
      got_next--;
      if (eof){
	return -1;
      }
      else
	{
	  return proc->arrival_time;
	}
    }	
   return proc->arrival_time;
  

}

struct proc_info* reader_get_next()
{
	got_next++;
	return proc;
}
/*Frees the one extra malloc done prior to eof*/
void reader_close()
{
	free(proc);
	return;
}



